`
https://leetcode.cn/problems/ones-and-zeroes/
`

/**
 * @param {string[]} strs
 * @param {number} m
 * @param {number} n
 * @return {number}
 */
var findMaxForm = function (strs, m, n) {
  // dp[i][j][k] 的定义：
  // 如果只使用前 i 个字符串，0 和 1 的限制分别为 j 和 k，可以装的最大字符串数量是 dp[i][j][k]
  const dp = Array.from({ length: strs.length + 1 }, () => Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0)))

  for (let i = 1; i <= strs.length; i++) {
    // 有一位的偏移，所以第 i 个字符串是strs[i - 1]
    const curStr = strs[i - 1]
    // 统计当前字符串里 '0' 和 '1' 的出现次数
    const [zeroCount, oneCount] = curStr.split('').reduce((acc, cur) => {
      if (cur === '0') acc[0]++
      else acc[1]++
      return acc
    }, [0, 0])

    for (let j = 0; j <= m; j++) {
      for (let k = 0; k <= n; k++) {
        if (j - zeroCount >= 0 && k - oneCount >= 0) {
          // 选放入或者不放入
          dp[i][j][k] = Math.max(
            dp[i - 1][j - zeroCount][k - oneCount] + 1,
            dp[i - 1][j][k]
          )
        } else {
          dp[i][j][k] = dp[i - 1][j][k]
        }
      }
    }
  }

  // 按照定义，返回结果
  return dp[strs.length][m][n]
};